package com.heyige.util;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * Redis服务类
 */
@Slf4j
@Component
public class RedisUtil {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    private static RedisTemplate<String, Object> staticRedisTemplate;

    @PostConstruct
    public void init() {
        staticRedisTemplate = this.redisTemplate;
        log.debug("RedisUtils 静态工具类初始化完成，redisTemplate 已注入");
    }

    /**
     * 设置缓存
     *
     * @param key   键
     * @param value 值
     */
    public static void set(String key, Object value) {
        try {
            staticRedisTemplate.opsForValue().set(key, value);
            log.debug("Redis设置缓存成功: key={}", key);
        } catch (Exception e) {
            log.error("Redis设置缓存失败: key={}, error={}", key, e.getMessage(), e);
            throw new RuntimeException("Redis设置缓存失败", e);
        }
    }

    /**
     * 设置缓存并指定过期时间
     *
     * @param key     键
     * @param value   值
     * @param timeout 过期时间
     * @param unit    时间单位
     */
    public static void set(String key, Object value, long timeout, TimeUnit unit) {
        try {
            staticRedisTemplate.opsForValue().set(key, value, timeout, unit);
            log.debug("Redis设置缓存成功: key={}, timeout={} {}", key, timeout, unit);
        } catch (Exception e) {
            log.error("Redis设置缓存失败: key={}, timeout={} {}, error={}", key, timeout, unit, e.getMessage(), e);
            throw new RuntimeException("Redis设置缓存失败", e);
        }
    }

    /**
     * 获取缓存
     *
     * @param key 键
     * @return 值
     */
    public static Object get(String key) {
        try {
            Object value = staticRedisTemplate.opsForValue().get(key);
            log.debug("Redis获取缓存成功: key={}, value={}", key, value);
            return value;
        } catch (Exception e) {
            log.error("Redis获取缓存失败: key={}, error={}", key, e.getMessage(), e);
            throw new RuntimeException("Redis获取缓存失败", e);
        }
    }

    /**
     * 删除缓存
     *
     * @param key 键
     * @return 是否删除成功
     */
    public static Boolean delete(String key) {
        try {
            Boolean result = staticRedisTemplate.delete(key);
            log.debug("Redis删除缓存成功: key={}, result={}", key, result);
            return result;
        } catch (Exception e) {
            log.error("Redis删除缓存失败: key={}, error={}", key, e.getMessage(), e);
            throw new RuntimeException("Redis删除缓存失败", e);
        }
    }

    /**
     * 判断缓存是否存在
     *
     * @param key 键
     * @return 是否存在
     */
    public static Boolean hasKey(String key) {
        try {
            Boolean result = staticRedisTemplate.hasKey(key);
            log.debug("Redis检查缓存存在: key={}, result={}", key, result);
            return result;
        } catch (Exception e) {
            log.error("Redis检查缓存存在失败: key={}, error={}", key, e.getMessage(), e);
            throw new RuntimeException("Redis检查缓存存在失败", e);
        }
    }

    /**
     * 设置过期时间
     *
     * @param key     键
     * @param timeout 过期时间
     * @param unit    时间单位
     * @return 是否设置成功
     */
    public static Boolean expire(String key, long timeout, TimeUnit unit) {
        try {
            Boolean result = staticRedisTemplate.expire(key, timeout, unit);
            log.debug("Redis设置过期时间成功: key={}, timeout={} {}, result={}", key, timeout, unit, result);
            return result;
        } catch (Exception e) {
            log.error("Redis设置过期时间失败: key={}, timeout={} {}, error={}", key, timeout, unit, e.getMessage(), e);
            throw new RuntimeException("Redis设置过期时间失败", e);
        }
    }

    /**
     * 获取过期时间
     *
     * @param key 键
     * @return 过期时间（秒）
     */
    static Long getExpire(String key) {
        try {
            Long result = staticRedisTemplate.getExpire(key);
            log.debug("Redis获取过期时间成功: key={}, result={}", key, result);
            return result;
        } catch (Exception e) {
            log.error("Redis获取过期时间失败: key={}, error={}", key, e.getMessage(), e);
            throw new RuntimeException("Redis获取过期时间失败", e);
        }
    }

    /**
     * 递增操作
     *
     * @param key   键
     * @param delta 递增步长
     * @return 递增后的值
     */
    public static Long increment(String key, long delta) {
        try {
            Long result = staticRedisTemplate.opsForValue().increment(key, delta);
            log.debug("Redis递增操作成功: key={}, delta={}, result={}", key, delta, result);
            return result;
        } catch (Exception e) {
            log.error("Redis递增操作失败: key={}, delta={}, error={}", key, delta, e.getMessage(), e);
            throw new RuntimeException("Redis递增操作失败", e);
        }
    }

    /**
     * 递减操作
     *
     * @param key   键
     * @param delta 递减步长
     * @return 递减后的值
     */
    public static Long decrement(String key, long delta) {
        try {
            Long result = staticRedisTemplate.opsForValue().decrement(key, delta);
            log.debug("Redis递减操作成功: key={}, delta={}, result={}", key, delta, result);
            return result;
        } catch (Exception e) {
            log.error("Redis递减操作失败: key={}, delta={}, error={}", key, delta, e.getMessage(), e);
            throw new RuntimeException("Redis递减操作失败", e);
        }
    }

    /**
     * Hash结构设置值
     *
     * @param key     键
     * @param hashKey hash键
     * @param value   值
     */
    public static void hSet(String key, String hashKey, Object value) {
        try {
            staticRedisTemplate.opsForHash().put(key, hashKey, value);
            log.debug("Redis Hash设置成功: key={}, hashKey={}, value={}", key, hashKey, value);
        } catch (Exception e) {
            log.error("Redis Hash设置失败: key={}, hashKey={}, error={}", key, hashKey, e.getMessage(), e);
            throw new RuntimeException("Redis Hash设置失败", e);
        }
    }

    /**
     * Hash结构获取值
     *
     * @param key     键
     * @param hashKey hash键
     * @return 值
     */
    public static Object hGet(String key, String hashKey) {
        try {
            Object value = staticRedisTemplate.opsForHash().get(key, hashKey);
            log.debug("Redis Hash获取成功: key={}, hashKey={}, value={}", key, hashKey, value);
            return value;
        } catch (Exception e) {
            log.error("Redis Hash获取失败: key={}, hashKey={}, error={}", key, hashKey, e.getMessage(), e);
            throw new RuntimeException("Redis Hash获取失败", e);
        }
    }

    /**
     * Hash结构删除值
     *
     * @param key     键
     * @param hashKey hash键
     * @return 是否删除成功
     */
    public static Long hDelete(String key, String hashKey) {
        try {
            Long result = staticRedisTemplate.opsForHash().delete(key, hashKey);
            log.debug("Redis Hash删除成功: key={}, hashKey={}, result={}", key, hashKey, result);
            return result;
        } catch (Exception e) {
            log.error("Redis Hash删除失败: key={}, hashKey={}, error={}", key, hashKey, e.getMessage(), e);
            throw new RuntimeException("Redis Hash删除失败", e);
        }
    }

}